package com.tk.utils;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.tk.eneity.PdfObj;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;

import javax.print.PrintService;
import java.awt.print.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class PdfUtil {

    private static final String PRINT_NAME = "Win32 Printer : Bar Code Printer T-4503E";
    private static final String IMAGE_CONTENT = "image";
    private static final String TEMPLATE_PATH = "templates/template.pdf";

    private PdfUtil() {

    }

    public static void generatePdf(PdfObj pdfObj) {
        if (ObjUtils.isEmpty(pdfObj)) return;

        Map<String, String> dataMap = new HashMap<>(16);
        dataMap.put("itemCode", pdfObj.getItemCode());
        dataMap.put("itemName", pdfObj.getItemName());
        dataMap.put("specifications", pdfObj.getSpecifications());
        dataMap.put("module", pdfObj.getModule());
        dataMap.put("boxNumber", pdfObj.getBoxNumber());
        dataMap.put("desc", pdfObj.getDesc());
        dataMap.put("batchNum", pdfObj.getBatchNum());
        dataMap.put("singleBoxQuantity", pdfObj.getSingleBoxQuantity());

        Map<String, String> photoMap = new HashMap<>(16);
        photoMap.put(IMAGE_CONTENT, pdfObj.getImageContent());

        try {
            byte[] bytes = fillTemplate(dataMap, photoMap, TEMPLATE_PATH);
            printPdf(bytes);
        } catch (Exception e) {
            log.error("ERROR PdfUtil.generatePdf cause:", e);
        }
    }

    public static void main(String[] args) throws PrinterException {
        Map<String, String> dataMap = new HashMap<>(16);
        dataMap.put("itemCode", "20100862AA01");
        dataMap.put("itemName", "方向盘开关(ICC+加热-哑光123456789123456789)");
        dataMap.put("specifications", "");
        dataMap.put("module", "JS01MC02");
        dataMap.put("boxNumber", "1");
        dataMap.put("desc", "这是描述内容xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaaaaaaaaaaaaaaaaaaaaaaaaa");
        dataMap.put("batchNum", "8465720240220172019");
        dataMap.put("singleBoxQuantity", "3");

        Map<String, String> photoMap = new HashMap<>(16);
        photoMap.put(IMAGE_CONTENT, "11哈哈12345-hello-world|12345");
        byte[] bytes = fillTemplate(dataMap, photoMap, TEMPLATE_PATH);
        printPdf(bytes);
    }

    public static void printPdf(byte[] bytes) throws PrinterException {
        if (ObjUtils.isEmpty(bytes)) {
            log.error("ERROR PdfUtil.printPdf bytes is null");
            return;
        }
        PrinterJob job = PrinterJob.getPrinterJob();
        // 遍历所有打印机的名称
        boolean flag = true;
        for (PrintService ps : PrinterJob.lookupPrintServices()) {
            // 选用指定打印机
            if (PRINT_NAME.equals(ps.toString())) {
                job.setPrintService(ps);
                flag = false;
                break;
            }
        }
        // 未找到指定打印机 结束任务
        if (flag) {
            log.error("ERROR PdfUtil.printPdf printer not found");
            return;
        }

        // 读取pdf文件
        try (PDDocument document = PDDocument.load(bytes)) {
            int pageCount = document.getNumberOfPages();
            job.setPageable(new PDFPageable(document));

            Paper paper = new Paper();
            // 设置打印纸张大小
            paper.setSize((80 / 25.4) * 72, (61 / 25.4) * 72); // 1/72 inch
            // 设置打印位置 坐标
            paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight()); // no margins
            // custom page format
            PageFormat pageFormat = new PageFormat();
            pageFormat.setPaper(paper);
            // override the page format
            Book book = new Book();
            // append all pages 设置一些属性 是否缩放 打印张数等
            book.append(new PDFPrintable(document, Scaling.SCALE_TO_FIT), pageFormat, pageCount);
            job.setPageable(book);
            // 开始打印
            job.print();

        } catch (Exception e) {
            log.error("ERROR PdfUtil.printPdf cause:", e);
        }
    }


    /**
     * 利用模板生成pdf
     *
     * @param dataMap      写入的数据
     * @param photoMap 图片数据
     * @param templatePath pdf模板路径
     */
    public static byte[] fillTemplate(Map<String, String> dataMap, Map<String, String> photoMap, String templatePath) {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            // 读取pdf模板
            PdfReader reader = new PdfReader(templatePath);
            PdfStamper stamper = new PdfStamper(reader, bos);
            AcroFields acroFields = stamper.getAcroFields();
            // 赋值
            for (String name : acroFields.getFields().keySet()) {
                String value = dataMap.get(name) != null ? dataMap.get(name) : null;
                acroFields.setField(name, value);
            }

            // 图片赋值
            for (Map.Entry<String, String> entry : photoMap.entrySet()) {
                if (Objects.isNull(entry.getKey())) {
                    continue;
                }
                String key = entry.getKey();
                String url = entry.getValue();
                // 根据地址读取需要放入pdf中的图片
                Image image = getImage(url);
                // 设置图片在哪一页
                PdfContentByte overContent = stamper.getOverContent(acroFields.getFieldPositions(key).get(0).page);
                // 获取模板中图片域的大小
                Rectangle signRect = acroFields.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                // 图片等比缩放
                image.scaleAbsolute(signRect.getWidth(), signRect.getHeight());
                // 图片位置
                image.setAbsolutePosition(x, y);
                // 在该页加入图片
                overContent.addImage(image);
            }

            // 如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.setFormFlattening(true);
            stamper.close();

            Document doc = new Document(PageSize.A4.rotate());
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfReader pdfReader = new PdfReader(bos.toByteArray());
            PdfDictionary pageN = pdfReader.getPageN(1);
            pageN.put(PdfName.ROTATE, new PdfNumber(90));
            PdfImportedPage importPage = copy.getImportedPage(pdfReader, 1);
            copy.addPage(importPage);
            doc.close();
            return out.toByteArray();
        } catch (Exception e) {
            log.error("ERROR PdfUtil.fillTemplate cause:", e);
            return null;
        }
    }


    /**
     * 图片样式
     */
    public static Image getImage(String content) throws IOException, BadElementException {
        byte[] bytes = ZXCodeUtil.generateCode(content);
        return Image.getInstance(bytes);
    }
}
